package com.globalwave.common.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.globalwave.base.BaseServiceImpl;
import com.globalwave.common.ArrayOrderList;
import com.globalwave.common.ArrayPageList;
import com.globalwave.common.C;
import com.globalwave.common.U;
import com.globalwave.common.entity.Field;
import com.globalwave.common.entity.View;
import com.globalwave.common.entity.VirtualEditForm;
import com.globalwave.common.entity.VirtualGrid;
import com.globalwave.common.exception.BusinessException;
import com.globalwave.system.entity.SessionUser;

public class VirtualModuleServiceImpl 
       extends BaseServiceImpl 
       implements VirtualModuleService {

	final static private short CREATE_OFFSET = 0 ;
	final static private short QUERY_OFFSET = 1 ;
	final static private short UPDATE_OFFSET = 2 ;
	final static private short DELETE_OFFSET = 3 ;
	
	private ViewService viewService ;
	private FieldService fieldService ;

    public VirtualGrid getUIMetaData(Long viewId, String viewCode) throws Exception {
    	return this.viewService.getUIMetaData(viewId, viewCode) ;
    }

    public VirtualEditForm getEditFormMetaData(String viewCode) throws Exception {
    	return this.viewService.getEditFormMetaData(viewCode) ;
    }

    private void checkPrivilege(SessionUser user, View view, short offset) {
    	
    	if (user == null) {
    		//E0000000001/'用户不存在！'
    		throw new BusinessException("E0000000001") ;//Privilege
    	}
    	
    	short pid = (short)(Short.parseShort(view.getPrivilege_code()) + offset) ;
    	
    	if (!user.hasPrivilege(pid)) {
    		// E0000000003', '用户没有操作权限，本次操作被禁止！
    		throw new BusinessException("E0000000003") ;//Privilege
    	}
    }
    
    public Map<String, String[]> create(
    		Map<String, String[]> entity, 
    		Long viewId,
    		SessionUser user) 
    throws Exception {
    	
    	View view = viewService.get(viewId)  ;

    	checkPrivilege(user, view, CREATE_OFFSET) ;
    	
        List<Field> fields = fieldService.queryByViewId(view.getEdit_view_id()) ;

        Map<String, Object> entity2Add = new HashMap<String, Object>() ;
    	for (Field field:fields) {
    		String code = field.getCode_() ;

    		Integer type = field.getType_() ;
    		Object[] values = entity.get(code) ;
    		
    		if (values == null) {

        		boolean isPK = !field.getIs_primary_key().equals(C.ZERO_INTEGER) ;
        		if (isPK) {
	        		entity2Add.put("$PK", code) ;
	        		entity2Add.put("$PK_SEQ", field.getDefault_()) ;
        		}
    			continue ;
    		}
    		
    		entity2Add.put(code, U.convert((String)values[0], type)) ;
    	}

    	view = viewService.get(view.getEdit_view_id()) ;
    	entity2Add.put("$TABLE", view.getTable_name()) ;
    	
        return (Map<String, String[]>) jdbcDao.insert(entity2Add, true);
    }

    
    public void update(Map<String, String[]> entity, Long viewId, SessionUser user) throws Exception {

    	View view = viewService.get(viewId) ;
    	checkPrivilege(user, view, UPDATE_OFFSET) ;

        List<Field> fields = fieldService.queryByViewId(view.getEdit_view_id()) ;

        Map<String, Object> entityPK = new HashMap<String, Object>() ;
        Map<String, Object> entity2Update = new HashMap<String, Object>() ;
    	for (Field field:fields) {
    		String code = field.getCode_() ;

    		Integer type = field.getType_() ;
    		Object[] values = entity.get(code) ;
    		
    		if (values == null) {
    			continue ;
    		}
    		
    		boolean isPK = C.TRUE_INTEGER.equals(field.getIs_primary_key()) ;
    		if (isPK) {
    			entityPK.put(code + "=", U.convert((String)values[0], type)) ;
    		} else {
    		    entity2Update.put(code, U.convert((String)values[0], type)) ;
    		}
    	}

    	view = viewService.get(view.getEdit_view_id()) ;
    	entity2Update.put("$TABLE", view.getTable_name()) ;
    	
        if (jdbcDao.update(entity2Update, entityPK) > 1) {
        	//E0101010001', '最多只有一条记录被更新！
        	throw new BusinessException("E0101010001"); 
        	//e.setCode("at most one row can be updated!!") ;
        }
    }

    public void deleteAll(String entitysAsString,Long viewId,SessionUser user) throws Exception {
    	Document entitysDoc = DocumentHelper.parseText(entitysAsString) ;
        
    	View view = viewService.get(viewId) ;
    	checkPrivilege(user, view, DELETE_OFFSET) ;
    	
        List<Field> fields = fieldService.queryByViewId(view.getEdit_view_id()) ;

        Map<String, Integer> entityPKCode = new HashMap<String, Integer>() ;
        
    	for (Field field:fields) {
    		String code = field.getCode_() ;

    		boolean isPK = C.TRUE_INTEGER.equals(field.getIs_primary_key()) ;
    		if (isPK) {
    			entityPKCode.put(code, field.getType_()) ;
    		} 
    	}

    	view = viewService.get(view.getEdit_view_id()) ;
		
		Map<String, Object> entityPK = new HashMap<String, Object>() ;
		
    	List<Element> elems = entitysDoc.getRootElement().elements("HashMap") ;
    	
    	for (int i = 0 ; i < elems.size() ; i ++) {
    		for (String key:entityPKCode.keySet()) {
    			Element element = elems.get(i) ;
    			Object codeValue = U.convert(element.element(key).getText(), entityPKCode.get(key)) ;
    			entityPK.put(key+"=", codeValue) ;
    		}

            if(jdbcDao.delete(view.getTable_name(), entityPK) > 1) {
            	// E0101010002', '最多只有一条记录被删除！
            	throw new BusinessException("E0101010002"); 
            }
    	}
        
    }

    public ArrayPageList<Map<String, Object>> query(
    		Map<String, String[]> criterion, 
            int pageIndex, 
            int pageSize,
            ArrayOrderList orderList,
            Long viewId,
            String viewCode, 
            SessionUser user) 
    throws Exception {
        
    	View view = (viewId != null?viewService.get(viewId):viewService.get(viewCode)) ;
    	checkPrivilege(user, view, QUERY_OFFSET) ;
    	
        List<Field> fields = fieldService.queryByViewId(view.getSearch_view_id()) ;

        Map<String, Object> criterion4Query = new HashMap<String, Object>() ;
    	for (Field field:fields) {
    		field.getOperator() ;
    		String code = field.getCode_() ;
    		String operator = field.getOperator() ;
    		if (operator == null) {
    			operator = "=" ;
    		}

    		Integer type = field.getType_() ;
    		Object[] values = criterion.get(code) ;
    		
    		if (values == null) {
    			continue ;
    		}
    		
    		for (int i = 0 ; i < values.length ; i ++) {
    			if ("like".equals(operator)) {
    			    values[i] = "%" + values[i] + "%" ;
    			} else {
    				values[i] = U.convert((String)values[i], type) ;
    			}
    		}
    		
    		criterion4Query.put(code + " " + operator, values) ;
    	}

    	String sql = view.getBefore_sql_1(); 
    	if (sql == null) {
    		sql = "select * from " + viewService.get(view.getEdit_view_id()).getTable_name() ;
    	}
    	
        return (ArrayPageList<Map<String, Object>>)jdbcDao.query(new StringBuffer(sql), criterion4Query, pageIndex, pageSize, orderList, HashMap.class);
    }


	@Override
	public void delete(Map<String, String[]> entity, SessionUser user) throws Exception {
		throw new NoSuchMethodError("delete method not support") ;
	}

	public void setViewService(ViewService viewService) {
		this.viewService = viewService;
	}

	public void setFieldService(FieldService fieldService) {
		this.fieldService = fieldService;
	}

}
